/*
 * Copyright (c) 2024 iSoftStone Education Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef __DEVICE_MGR_H__
#define __DEVICE_MGR_H__

// 在 smart_home_config.h 中定义
#define LIGHT_THRESHOLD  1000

#include <stdint.h>
#include <stdbool.h>
#include "lz_hardware/pinctrl.h"

#include "door.h"


#define MQ2_PIN GPIO0_PC4
#define CAL_PPM 20 // 校准环境中PPM值
#define RL 1       // RL阻值

#define I2C_HANDLE EI2C0_M2
// #define MOTOR_PWM_HANDLE EPWMDEV_PWM6_M0
// #define LED_R_GPIO_HANDLE GPIO0_PB5
// #define LED_G_GPIO_HANDLE GPIO0_PB4
// #define LED_B_GPIO_HANDLE GPIO1_PD0
// #define GPIO_BODY_INDUCTION GPIO0_PA3
#define MOTOR_PWM_B1A GPIO0_PA3
#define MOTOR_PWM_B2A GPIO0_PB5
// #define LIGHT_CTL_PIN GPIO0_PB4

#define DOOR_ENTRY_PIN EPWMDEV_PWM1_M1
#define DOOR_GARAGE_PIN EPWMDEV_PWM0_M1
#define WINDOW_PIN EPWMDEV_PWM7_M1

#define SHT30_I2C_ADDRESS 0x44
#define KEYBOARD_I2C_ADDRESS 0x20
#define BH1750_I2C_ADDRESS 0x23
#define AHT20_I2C_ADDRESS 0x38

#define KEYPAD_ROWS 4
#define KEYPAD_COLS 4
#define DEBOUNCE_DELAY_MS 200

// 定义颜色常量
#define COLOR_WHITE 0xFFFFFF
#define COLOR_OFF   0x000000

extern bool g_is_entry_door_open;
extern bool g_is_garage_door_open;
extern bool g_is_window_open;
extern bool g_is_light_on;

typedef struct
{
    int                 init;               //初始化状态
    int                 port;               //端口
    Pinctrl             adc;                //io总线
} iss_adc_dev_s;
typedef iss_adc_dev_s iss_mq2_dev_s;

static float m_r0; // 元件在干净空气中的阻值
static iss_mq2_dev_s m_iss_mq2 =
{
    .init = 0,
    .port = 4,
    .adc = {.gpio = MQ2_PIN, .func = MUX_FUNC1, .type = PULL_NONE, .drv = DRIVE_KEEP, .dir = LZGPIO_DIR_IN, .val = LZGPIO_LEVEL_KEEP},
};

//GRF_SOC_CON29寄存器结构体
typedef union
{
    uint32_t value;
    struct
    {
        uint16_t grf_saradc_ana_reg_low: 4;
        uint16_t grf_saradc_vol_sel: 1;
        uint16_t grf_saradc_ana_reg_high: 11;
        struct 
        {
            uint16_t grf_saradc_ana_reg_low: 4;
            uint16_t grf_saradc_vol_sel: 1;
            uint16_t grf_saradc_ana_reg_high: 11;
        } rw;
    };
} GRF_SOC_CON29;

// 消抖状态机
typedef enum {
    DEBOUNCE_STATE_IDLE,
    DEBOUNCE_STATE_PRESS_DETECTED,
    DEBOUNCE_STATE_WAIT_RELEASE
} DebounceState;


/**
 * @brief Initialize I2C devices.
 *
 * This function initializes the I2C devices used in the system, preparing them for subsequent operations.
 * It should be called before any other I2C-related functions are used.
 *
 * @return void
 */
void i2c_dev_init(void);

/**
 * @brief Get light intensity value from BH1750 sensor.
 *
 * This function retrieves the current light intensity (in lux) from the BH1750 sensor via I2C.
 * The measured value is stored in the provided output parameter.
 *
 * @param[out] lux Pointer to store the measured light intensity value (in lux).
 * @return int Returns 0 on success, or a negative error code on failure.
 */
int get_light_value(float *lux);

/**
 * @brief Get temperature and humidity values from the sensor.
 *
 * This function retrieves the current temperature and humidity values from the I2C sensor.
 * The measured values are stored in the provided output parameters.
 *
 * @param[out] temperature Pointer to store the measured temperature value.
 * @param[out] humidity    Pointer to store the measured humidity value.
 * @return int Returns 0 on success, or a negative error code on failure.
 */
int get_tmp_hum_value(float *temperature, float *humidity);

/**
 * @brief Check for a key press on the I2C keypad.
 *
 * This function scans the 4x4 matrix keypad connected via I2C and returns the pressed key.
 * It also handles key debouncing using a simple debounce state machine.
 *
 * @param[out] key Pointer to store the pressed key character.
 * @return int Returns 0 if a key is successfully read, or a negative error code otherwise.
 */
int get_key_pressed(char *key);

/**
 * @brief Initialize GPIO devices.
 *
 * This function initializes the GPIO pins used for controlling LEDs, motors, and other peripherals.
 *
 * @return void
 */
void gpio_dev_init(void);

/**
 * @brief Control the light based on ambient light level.
 *
 * This function reads the ambient light level and turns the light on or off depending on whether
 * it is below or above the defined [LIGHT_THRESHOLD]
 *
 * @return int Returns 0 on success, or a negative error code on failure.
 */
int light_control();

/**
 * @brief Initialize door control hardware.
 *
 * This function initializes the hardware required for door control operations.
 *
 * @return int Returns 0 on success, or a negative error code on failure.
 */
int door_init();

/**
 * @brief Control the actuation of doors based on input conditions.
 *
 * This function implements the logic for controlling multiple doors (e.g., entry door, garage door)
 * based on external triggers or user inputs.
 *
 * @return int Returns 0 on success, or a negative error code on failure.
 */
int door_actuator_control();

/**
 * @brief Initialize LCD display device.
 *
 * This function initializes the LCD display hardware for UI rendering.
 *
 * @return void
 */
void lcd_dev_init(void);

/**
 * @brief Load the default UI layout on the LCD screen.
 *
 * This function displays the initial smart home UI layout on the LCD screen.
 *
 * @return void
 */
void lcd_load_ui(void);

/**
 * @brief Set the light state indicator on the LCD.
 *
 * This function updates the light state (on/off) indicator on the LCD UI.
 *
 * @param[in] state Boolean indicating whether the light is on or off
 * @return void
 */
void lcd_set_light_state(bool state);

/**
 * @brief Set the auto mode indicator on the LCD.
 *
 * This function updates the auto/manual mode indicator on the LCD UI.
 *
 * @param[in] state Boolean indicating whether the system is in auto mode or manual mode
 * @return void
 */
void lcd_set_auto_state(bool state);

/**
 * @brief Initialize MQ2 gas sensor ADC device.
 *
 * This function initializes the ADC channel associated with the MQ2 gas sensor.
 *
 * @param[in,out] adc Pointer to the ADC device structure to initialize.
 * @return uint32_t Returns 0 on success, or an error code on failure.
 */
uint32_t mq2_dev_init(iss_mq2_dev_s *adc);

/**
 * @brief Calibrate the MQ2 gas sensor for baseline PPM.
 *
 * This function calculates and stores the baseline resistance value 
 * of the MQ2 sensor in clean air for calibration purposes.
 *
 * @return void
 */
void calibrate_mq2_ppm(void);

/**
 * @brief Get the current gas concentration in PPM.
 *
 * This function calculates and returns the current gas concentration (in parts per million - PPM)
 * based on the sensor reading and previously calibrated baseline.
 *
 * @return float The estimated gas concentration in PPM.
 */
/**
 * @brief Get the current gas concentration in PPM.
 * This function calculates and returns the current gas concentration (in parts per million - PPM)
 * based on the sensor reading and previously calibrated baseline.
 * @param[out] ppm Pointer to store the calculated PPM value.
 * @return int Returns 0 on success, or a negative error code on failure.
 */
int get_mq2_ppm(float *ppm);

#endif
